//高阶函数不仅能把函数作为参数，还能将函数作为返回值
/*
var arr=[1,3,5,7,9];
function n1 (arr) {
    var sum=function () {
       
       return arr.reduce(function (x,y) {
           return x+y;

            
        })
    
    }
        return sum;//返回的是一个函数
}

var f=n1(arr)
console.log(f());
var f1=n1([1,2,3,4,5,6,7,8,9,10])
var f2=n1([1,2,3,4,5,6,7,8,9,10])
console.log(f1());
console.log(f2());

if (f1===f2) {
    console.log("测试通过！！！"); 
}
else{
    console.log("测试失败！！！表明这传入一样的数组参数，然而结果返回的并不是同一个函数");
}
 */


//什么是闭包？
// 注意到返回的函数在其定义内部引用了局部变量arr，所以，当一个函数返回了一个函数后，
// 其内部的局部变量还被新函数引用，所以，闭包用起来简单，实现起来可不容易。

// 另一个需要注意的问题是，返回的函数并没有立刻执行，而是直到调用了f()才执行。
// 我们来看一个例子：
/*
var arr=[];//空数组

function  Count() {

    for (let i = 0; i <=3; i++) {
        arr.push(function () {
                return i*i;
            
            }
        )
        
    }

    return arr;//返回的是装着函数的数组,返回值是函数且引用着外部变量时，称为闭包
    
}
var result=Count();

var f1=result[0];
var f2=result[1];
var f3=result[2];


console.log(f1());
console.log(f2());
console.log(f3());
 */

//此处 i 的定义用的是let ，而不是var，那我一定要用var i=0呢？
//这时候就要用到匿名函数
//即：
/*
function (x) {
    
}(3);//直接调用，但是会报错！！！
理论上匿名函数可以直接接在函数后面调用由于JavaScript语法解析的问题，
会报SyntaxError错误，因此需要用括号把整个函数定义括起来：

console.log(  function (x) {return x*x}(3)  )此处的log()的括号也可以
*/

/* 
var arr=[];

function Count(arr) {

    for (var i = 1; i <= 4; i++) {

         arr.push((function(n) {
                return  function () {
                 
                    return n*n;
                     
                 }
            })(i)
        )
    } 
    return arr;
}

var result=Count(arr);


var f1=result[0];
var f2=result[1];
var f3=result[2];
var f4=result[3];


console.log(f1());
console.log(f2());
console.log(f3());
console.log(f4());
*/


//那么说了那么多，难道闭包就是为了延迟执行？
//然而不是，js里没有class机制，不能像java和c#里一样对成员变量封装时进行类似
//public或private的修饰，闭包就做到类似private的修饰效果，外部代码无法访问
//到完成闭包的函数里定义的变量


/*
function  create_counter (initial){
    var x=initial ||0
    return {
        c:function () {
            return x=x+1;
            
        }
    }
}
var b=create_counter();

console.log(b.c());
console.log(b.c());
console.log(b.c());
console.log(b.c());
*/





